/*
 * PANEButtonElement.cpp
 *
 *  Created on: Apr 27, 2009
 *      Author: wrice
 */
//#include ".h"
#include "PANEImp.h"
namespace PANEImp {

string PANEButtonElement::TagName = "BUTTON";
string PANEButtonElement::AttrNameNormalImage = "NORMAL_IMAGE";
string PANEButtonElement::AttrNameMouseOverImage = "MOUSE_OVER_IMAGE";
string PANEButtonElement::AttrNameMouseDownImage = "MOUSE_DOWN_IMAGE";
string PANEButtonElement::AttrNameDisabledImage = "DISABLED_IMAGE";
string PANEButtonElement::AttrNameDisabled = "DISABLED";
string PANEButtonElement::AttrValueDisabledTrue = "TRUE";
string PANEButtonElement::AttrValueDisabledFalse = "FALSE";

struct PANEButtonElement::Imp {

	class MouseOverEventListener : IMPLEMENTS( EventListener ) {
	public:
		virtual void handleEvent(Event * evt) {
			MouseEvent * mouseEvt = dynamic_cast< MouseEvent * >( evt );
			EventTarget * target = mouseEvt->getTarget();
			VisualButtonForPANE * btn = dynamic_cast< VisualButtonForPANE * >( target );
			btn->setButtonState( ButtonMouseOverState );
		}
	};

	class MouseDownEventListener : IMPLEMENTS( EventListener ) {
	public:
		virtual void handleEvent(Event * evt) {
			MouseEvent * mouseEvt = dynamic_cast< MouseEvent * >( evt );
			EventTarget * target = mouseEvt->getTarget();
			VisualButtonForPANE * btn = dynamic_cast< VisualButtonForPANE * >( target );
			btn->setButtonState( ButtonMouseDownState );
		}
	};

	class MouseOutEventListener : IMPLEMENTS( EventListener ) {
	public:
		virtual void handleEvent(Event * evt) {
			MouseEvent * mouseEvt = dynamic_cast< MouseEvent * >( evt );
			EventTarget * target = mouseEvt->getTarget();
			VisualButtonForPANE * btn = dynamic_cast< VisualButtonForPANE * >( target );
			btn->setButtonState( ButtonNormalState );
		}
	};
};

PANEButtonElement::PANEButtonElement( PANEDocument * ownerDocument )
: PANEElement(TagName, ownerDocument)
, buttonState_(ButtonNormalState)
{
	this->addEventListener( MouseEventImp::EVENT_MOUSE_OVER, new Imp::MouseOverEventListener(), false );
	this->addEventListener( MouseEventImp::EVENT_MOUSE_DOWN, new Imp::MouseDownEventListener(), false );
	this->addEventListener( MouseEventImp::EVENT_MOUSE_UP, new Imp::MouseOverEventListener(), false );
	this->addEventListener( MouseEventImp::EVENT_MOUSE_OUT, new Imp::MouseOutEventListener(), false );

	cvImgs_[0] = cvImgs_[1] = cvImgs_[2] = cvImgs_[3] = NULL;
	loadedFiles_[0] = loadedFiles_[1] = loadedFiles_[2] = loadedFiles_[3] = "";
}

PANEButtonElement::~PANEButtonElement() {
	if( cvImgs_[ButtonNormalState] ) cvReleaseImage( &(cvImgs_[ButtonNormalState]) );
	if( cvImgs_[ButtonMouseOverState] ) cvReleaseImage( &(cvImgs_[ButtonMouseOverState]) );
	if( cvImgs_[ButtonMouseDownState] ) cvReleaseImage( &(cvImgs_[ButtonMouseDownState]) );
	if( cvImgs_[ButtonDisabledState] ) cvReleaseImage( &(cvImgs_[ButtonDisabledState]) );
}

void PANEButtonElement::setNormalImage( string url ) {
	setAttribute(AttrNameNormalImage, url );
}
void PANEButtonElement::setMouseOverImage( string url ) {
	setAttribute(AttrNameMouseOverImage, url );
}
void PANEButtonElement::setMouseDownImage( string url ) {
	setAttribute(AttrNameMouseDownImage, url );
}
void PANEButtonElement::setDisabledImage( string url ) {
	setAttribute(AttrNameDisabledImage, url );
}

bool PANEButtonElement::getDisabled() {
	return this->getAttribute(AttrNameDisabled) == AttrValueDisabledTrue;
}

string PANEButtonElement::getNormalImage() {
	return getAttribute(AttrNameNormalImage);
}
string PANEButtonElement::getMouseOverImage() {
	return getAttribute(AttrNameMouseOverImage);
}
string PANEButtonElement::getMouseDownImage() {
	return getAttribute(AttrNameMouseDownImage);
}
string PANEButtonElement::getDisabledImage() {
	return getAttribute(AttrNameDisabledImage);
}

DOMString PANEButtonElement::getNormalImageURL() {
	return getNormalImage();
}

DOMString PANEButtonElement::getMouseOverImageURL() {
	return getMouseOverImage();
}

DOMString PANEButtonElement::getMouseDownImageURL() {
	return getMouseDownImage();
}

DOMString PANEButtonElement::getDisabledImageURL() {
	return getDisabledImage();
}

unsigned short PANEButtonElement::getLoadedImages() {
	if( false == getIsLoaded() ) loadImageFiles();
	unsigned short rst = 0;
	if( cvImgs_[ButtonNormalState] ) rst |= VisualButtonForPANE::NORMAL_IMAGE;
	if( cvImgs_[ButtonMouseOverState] ) rst |= VisualButtonForPANE::MOUSE_OVER_IMAGE;
	if( cvImgs_[ButtonMouseDownState] ) rst |= VisualButtonForPANE::MOUSE_DOWN_IMAGE;
	if( cvImgs_[ButtonDisabledState] ) rst |= VisualButtonForPANE::DISABLED_IMAGE;
	return rst;
}

unsigned short PANEButtonElement::getButtonState() {
	return buttonState_;
}

void PANEButtonElement::setDisabled( bool disabled ) {
	setAttribute( AttrNameDisabled, disabled ? AttrValueDisabledTrue : AttrValueDisabledFalse );
}

void PANEButtonElement::setButtonState( unsigned short buttonState ) {
	if( buttonState_ != buttonState ) requestRepaint();
	buttonState_ = buttonState;
}

bool PANEButtonElement::getIsDisabled() {
	return getDisabled();
}

void PANEButtonElement::render( IplImage * img ) {
	if( false == isRepaintRequested() ) return;
	if( false == getVisible() ) return;
	if( false == getIsLoaded() ) loadImageFiles();
	if( false == getIsLoaded() ) return;

	const int maxWidth = img->width;
	const int maxHeight = img->height;
	const long leftOffset = getLeftOffset();
	const long topOffset = getTopOffset();
	const IplImage * const cvImg =  cvImgs_[ getButtonState() ];

	for( int i = 0; i < cvImg->height && i + topOffset < maxHeight; ++i )
		for( int j = 0; j < cvImg->width && j + leftOffset < maxWidth; ++j ) {
			const CvScalar aDot = cvGet2D( cvImg, i, j );
			cvSet2D( img, topOffset + i, leftOffset + j, aDot );
		}

	repainted();
}

unsigned long PANEButtonElement::getWidth() {
	if( hasDesiredWidth() ) return PANEElement::getWidth();
	return getActualWidth(0);
}
unsigned long PANEButtonElement::getHeight() {
	if( hasDesiredHeight() ) return PANEElement::getHeight();
	return getActualHeight(0);
}

unsigned long PANEButtonElement::getActualWidth( unsigned long availableWidth ) {
	if( false == getIsLoaded() ) loadImageFiles();
	const IplImage * const cvImg =  cvImgs_[ getButtonState() ];
	if( NULL == cvImg ) return 0;
	return cvImg->width;
}

unsigned long PANEButtonElement::getActualHeight( unsigned long availableWidth ) {
	if( false == getIsLoaded() ) loadImageFiles();
	const IplImage * const cvImg =  cvImgs_[ getButtonState() ];
	if( NULL == cvImg ) return 0;
	return cvImg->height;
}

bool PANEButtonElement::getIsLoaded() {
	if( getNormalImage() != loadedFiles_[ButtonNormalState] ) return false;
	if( getMouseOverImage() != loadedFiles_[ButtonMouseOverState] ) return false;
	if( getMouseDownImage() != loadedFiles_[ButtonMouseDownState] ) return false;
	if( getDisabledImage() != loadedFiles_[ButtonDisabledState] ) return false;

	if( !getNormalImage().empty() && ! cvImgs_[ ButtonNormalState] ) return false;
	if( !getMouseOverImage().empty() && ! cvImgs_[ ButtonMouseOverState] ) return false;
	if( !getMouseDownImage().empty() && ! cvImgs_[ ButtonMouseDownState] ) return false;
	if( !getDisabledImage().empty() && ! cvImgs_[ ButtonDisabledState] ) return false;

	return true;
}

void PANEButtonElement::loadImageFiles() {
	if( cvImgs_[ButtonNormalState] ) cvReleaseImage( &(cvImgs_[ButtonNormalState]) );
	if( false == getNormalImage().empty() ) {
		cvImgs_[ButtonNormalState] = cvLoadImage( getNormalImage().c_str() );
		loadedFiles_[ButtonNormalState] = getNormalImage();
		requestRepaint();
	}

	if( cvImgs_[ButtonMouseOverState] ) cvReleaseImage( &(cvImgs_[ButtonMouseOverState]) );
	if( false == getMouseOverImage().empty() ) {
		cvImgs_[ButtonMouseOverState] = cvLoadImage( getMouseOverImage().c_str() );
		loadedFiles_[ButtonMouseOverState] = getMouseOverImage();
		requestRepaint();
	}

	if( cvImgs_[ButtonMouseDownState] ) cvReleaseImage( &(cvImgs_[ButtonMouseDownState]) );
	if( false == getMouseDownImage().empty() ) {
		cvImgs_[ButtonMouseDownState] = cvLoadImage( getMouseDownImage().c_str() );
		loadedFiles_[ButtonMouseDownState] = getMouseDownImage();
		requestRepaint();
	}

	if( cvImgs_[ButtonDisabledState] ) cvReleaseImage( &(cvImgs_[ButtonDisabledState]) );
	if( false == getDisabledImage().empty() ) {
		cvImgs_[ButtonDisabledState] = cvLoadImage( getDisabledImage().c_str() );
		loadedFiles_[ButtonDisabledState] = getDisabledImage();
		requestRepaint();
	}
}

}

